/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.aspose.nbplugin.newfile;

import com.aspose.nbplugin.examplesmodel.Data;
import com.aspose.nbplugin.examplesmodel.Example;
import com.aspose.nbplugin.examplesmodel.Examples;
import com.aspose.nbplugin.examplesmodel.Folder;
import com.aspose.nbplugin.examplesmodel.Folders;
import com.aspose.nbplugin.examplesmodel.ObjectFactory;
import com.aspose.nbplugin.progressmonitor.AbstractTask;
import com.aspose.nbplugin.progressmonitor.TasksExecutor;
import com.aspose.nbplugin.newfile.otherexamples.OtherExamplesManager;
import com.aspose.nbplugin.utils.AsposeComponentsManager;
import com.aspose.nbplugin.utils.AsposeConstants;
import com.aspose.nbplugin.utils.AsposeJavaComponent;
import com.aspose.nbplugin.utils.AsposeJavaComponents;
import com.aspose.nbplugin.utils.CustomtMutableTreeNode;
import com.aspose.nbplugin.utils.GitHelper;
import java.awt.Color;
import java.io.File;
import java.io.FilenameFilter;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.netbeans.api.progress.aggregate.ProgressContributor;
import org.openide.util.Exceptions;
import org.netbeans.api.project.Project;
import org.netbeans.spi.project.ui.templates.support.Templates;
import org.openide.WizardDescriptor;
import org.openide.awt.StatusDisplayer;
import org.openide.filesystems.FileObject;

/**
 * @author Shoaib Khan
 */
public final class AsposeNewFileVisualPanel1 extends JPanel {

    Project selectedProject;
    boolean examplesNotAvailable;
    AsposeNewFileWizardPanel1 panel;

    /**
     * Creates new form AsposeNewFileVisualPanel1
     */
    public AsposeNewFileVisualPanel1(AsposeNewFileWizardPanel1 panel) {
        AsposeConstants.println("AsposeNewFileVisualPanel1 is called ...");
        initComponents();
        initComponentsUser();
        this.panel = panel;
    }

    private void initComponentsUser() {
        AsposeJavaComponents components = new AsposeJavaComponents();
        examplesNotAvailable = false;
        getComponentSelection().removeAllItems();
        getComponentSelection().addItem("Select component");

        CustomtMutableTreeNode top = new CustomtMutableTreeNode("");
        DefaultTreeModel model = (DefaultTreeModel) getExamplesTree().getModel();
        model.setRoot(top);
        model.reload(top);

        validateDialog();
    }

    @Override
    public String getName() {
        return "Component and Example";
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        componentSelection = new javax.swing.JComboBox();
        jLabel1 = new javax.swing.JLabel();
        jLabelMessage = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        examplesTree = new javax.swing.JTree();

        jPanel1.setBackground(new java.awt.Color(255, 255, 255));
        jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        jPanel1.setForeground(new java.awt.Color(255, 255, 255));

        jLabel2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/long_banner.png"))); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(AsposeNewFileVisualPanel1.class, "AsposeNewFileVisualPanel1.jLabel2.text")); // NOI18N

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jLabel2)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jLabel2)
        );

        componentSelection.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
        componentSelection.setSelectedIndex(-1);
        componentSelection.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                componentSelectionActionPerformed(evt);
            }
        });
        componentSelection.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                componentSelection_Propertychanged(evt);
            }
        });

        org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(AsposeNewFileVisualPanel1.class, "AsposeNewFileVisualPanel1.jLabel1.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(jLabelMessage, org.openide.util.NbBundle.getMessage(AsposeNewFileVisualPanel1.class, "AsposeNewFileVisualPanel1.jLabelMessage.text")); // NOI18N

        examplesTree.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                examplesTree_clicked(evt);
            }
        });
        jScrollPane2.setViewportView(examplesTree);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(jLabel1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(componentSelection, javax.swing.GroupLayout.PREFERRED_SIZE, 198, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(jLabelMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 361, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jScrollPane2)
                    .addContainerGap()))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(componentSelection, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 244, Short.MAX_VALUE)
                .addComponent(jLabelMessage, javax.swing.GroupLayout.PREFERRED_SIZE, 12, javax.swing.GroupLayout.PREFERRED_SIZE))
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup()
                    .addGap(126, 126, 126)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 229, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
        );
    }// </editor-fold>//GEN-END:initComponents
    //=========================================================================

    public String getSelectedProjectRootPath() {
        String path = null;

        FileObject fo = selectedProject.getProjectDirectory();
        path = fo.getPath();

        return path;
    }

    //=========================================================================
    void read(WizardDescriptor settings) {
        selectedProject = Templates.getProject(settings);
        FileObject dir = selectedProject.getProjectDirectory();
        AsposeConstants.println(" === New File Visual Panel.read() === " + dir.getName());
        populateComponentsList();
    }

    //=========================================================================
    private boolean populateComponentsList() {
        File file = new File(getSelectedProjectRootPath() + File.separator + "lib");
        String[] directories = file.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return new File(dir, name).isDirectory();
            }
        });

        getComponentSelection().removeAllItems();
        getComponentSelection().addItem("Select component");
        for (String directorie : directories) {
            if (!directorie.equals("CopyLibs") && !directorie.equals("ExamplesFrameWorks")) {
                getComponentSelection().addItem(directorie);
            }
        }
        return true;
    }

    //=========================================================================
    private void componentSelectionActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_componentSelectionActionPerformed
    {//GEN-HEADEREND:event_componentSelectionActionPerformed
        SwingWorker sw = new SwingWorker<String, Void>() {
            @Override
            protected String doInBackground() {

                String item = (String) getComponentSelection().getSelectedItem();
                if (item != null && item.equals("Select component")) {
                    return null;
                }
                diplayMessage("Please wait, Preparing to refresh examples", true);
                CustomtMutableTreeNode top = new CustomtMutableTreeNode("");
                DefaultTreeModel model = (DefaultTreeModel) getExamplesTree().getModel();
                model.setRoot(top);
                model.reload(top);

                final AsposeJavaComponent component = AsposeJavaComponents.list.get(item);
                TasksExecutor tasksExecution = new TasksExecutor("Retrieving Examples . . .");
                tasksExecution.addNewTask(new AbstractTask("Retrieving Examples ...") {
                    public void run() {
                        p.start(10);
                        checkAndUpdateRepo(component,p);
                        p.finish();
                    }
                });
                tasksExecution.processTasks();
                validateDialog();
                return null;
            }
        };

        sw.execute();
    }//GEN-LAST:event_componentSelectionActionPerformed
    boolean valid(WizardDescriptor wizardDescriptor) {
        AsposeConstants.println("AsposeNewFileVisualPanel1 valid  called..");
        return validateDialog();
    }
//=========================================================================

    @Override
    public void validate() {
        AsposeConstants.println("AsposeNewFileVisualPanel1 validate called..");
    }

//=========================================================================
    public boolean validateDialog() {
        if (isExampleSelected()) {
            clearMessage();
            return true;
        }
        if (getComponentSelection().getSelectedIndex() == 0) {
            diplayMessage("Please select component", true);
            return false;
        } else if (!isExampleSelected()) {
            diplayMessage("Please select example", true);
            return false;
        }

        clearMessage();
        return true;
    }

    //=========================================================================
    private boolean isExampleSelected() {
        CustomtMutableTreeNode comp = (CustomtMutableTreeNode) getExamplesTree().getLastSelectedPathComponent();
        if (comp == null) {
            return false;
        }
        try {
            String path = comp.getExPath();
            Example ex = comp.getExample();
            if (ex == null) {
                return false;
            }
        } catch (Exception ex) {
            return false;
        }
        return true;
    }

    //=========================================================================
    private void diplayMessage(String message, boolean error) {
        if (error) {
            jLabelMessage.setForeground(Color.RED);
        } else {
            jLabelMessage.setForeground(Color.GREEN);
        }
        jLabelMessage.setText(message);
    }

    //=========================================================================
    private void clearMessage() {
        jLabelMessage.setText("");
    }

    //=========================================================================
    public int showMessage(String title, String message, int buttons, int icon) {
        int result = JOptionPane.showConfirmDialog(null, message, title, buttons, icon);
        return result;
    }

    //========================================================================= TODO Adeel
    private void checkAndUpdateRepo(AsposeJavaComponent component,ProgressContributor p) {
        if (null == component) {
            return;
        }
        if (null == component.get_remoteExamplesRepository()) {
            showMessage("Examples not available", component.get_name() + " - " + AsposeConstants.EXAMPLES_NOT_AVAILABLE_MESSAGE, JOptionPane.CLOSED_OPTION, JOptionPane.INFORMATION_MESSAGE);
            examplesNotAvailable = true;
            return;
        } else {
            examplesNotAvailable = false;
        }
        if (GitHelper.isExamplesDefinitionsPresent(component)) {
            try {
                p.progress(5);
                StatusDisplayer.getDefault().setStatusText("Checking for new examples ...");
                GitHelper.updateRepository(component,p); // added by shoaib.khan@aspose.com to always show the updated examples as soon as these are added on github.
                StatusDisplayer.getDefault().setStatusText("Populating examples tree ...");
                populateExamplesTree(component);
                p.progress(5);
            } catch (Exception e) {
            }

        } else {
            int result = showMessage("Examples download required", component.get_name() + " - " + AsposeConstants.EXAMPLES_DOWNLOAD_REQUIRED, JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE);
            if (result == JOptionPane.YES_OPTION) {
                if (AsposeComponentsManager.isIneternetConnected()) {
                    p.progress(2);
                    StatusDisplayer.getDefault().setStatusText("Downloading examples ...");
                    GitHelper.updateRepository(component,p);
            
                    if (GitHelper.isExamplesDefinitionsPresent(component)) {
                        try {
                            populateExamplesTree(component);

                        } catch (Exception e) {
                        }

                    }
                    p.progress(2);
                } else {
                    showMessage(AsposeConstants.INTERNET_CONNECTION_REQUIRED_MESSAGE_TITLE, component.get_name() + " - " + AsposeConstants.EXAMPLES_INTERNET_CONNECTION_REQUIRED_MESSAGE, JOptionPane.OK_OPTION, JOptionPane.INFORMATION_MESSAGE);
                }
            }
        }
    }

    //=========================================================================
    private void populateExamplesTree(AsposeJavaComponent asposeComponent) {
        String examplesDefinitionFile = GitHelper.getExamplesDefinitionsPath(asposeComponent);
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
            Unmarshaller unmarshaller;
            String componentName = asposeComponent.get_name();
            StatusDisplayer.getDefault().setStatusText("Populating "+componentName+" examples ...");
            unmarshaller = jaxbContext.createUnmarshaller();

            Data data = (Data) unmarshaller.unmarshal(new File(examplesDefinitionFile));
            getExamplesTree().removeAll();
            CustomtMutableTreeNode top = new CustomtMutableTreeNode(componentName);
            top.setExPath("src");
            List<Folders> rootFoldersList = data.getFolders();

            parseFoldersTree(rootFoldersList, top);
            parseExamples(data.getExamples(), top);

            // Added by adeel.ilyas@aspose.com - Integration of Apache POI Examples / Other FrameWork Examples
            // Add Apache POI related Aspose API (comparison) examples if available any.
            OtherExamplesManager.addOtherExamples(top, asposeComponent);
            // adeel.ilyas@aspose.com 

            DefaultTreeModel model = (DefaultTreeModel) getExamplesTree().getModel();
            model.setRoot(top);
            model.reload(top);
            getExamplesTree().expandPath(new TreePath(top.getPath()));
        } catch (JAXBException ex) {
            Exceptions.printStackTrace(ex);
        }
    }
        //=========================================================================

    //=========================================================================
    void parseFoldersTree(List<Folders> rootFoldersList, CustomtMutableTreeNode parentItem) {
        for (Folders folders : rootFoldersList) {
            // Get list of folder
            List<Folder> folderList = folders.getFolder();
            for (Folder folder : folderList) {
                CustomtMutableTreeNode child = new CustomtMutableTreeNode(folder.getTitle());
                child.setExPath(parentItem.getExPath() + File.separator + folder.getFolderName());
                parseExamples(folder.getExamples(), child);
                parseFoldersTree(folder.getFolders(), child);
                parentItem.add(child);
            }
        }
    }

    //=========================================================================
    void parseExamples(List<Examples> examplesList, CustomtMutableTreeNode parentItem) {
        for (Examples examples : examplesList) {
            List<Example> exampleList = examples.getExample();
            for (Example example : exampleList) {
                // false: do not run
                parseExample(example, parentItem);
            }
        }
    }

    //=========================================================================
    void parseExample(Example example, CustomtMutableTreeNode parentItem) {
        CustomtMutableTreeNode child = new CustomtMutableTreeNode(example.getTitle());
        child.setExample(example);
        child.setExPath(parentItem.getExPath() + File.separator + example.getFolderName());
        parentItem.add(child);
    }

    //=========================================================================
    private void componentSelection_Propertychanged(java.beans.PropertyChangeEvent evt)//GEN-FIRST:event_componentSelection_Propertychanged
    {//GEN-HEADEREND:event_componentSelection_Propertychanged

    }//GEN-LAST:event_componentSelection_Propertychanged

    private void examplesTree_clicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_examplesTree_clicked
        // TODO add your handling code here:
        TreePath path = getExamplesTree().getSelectionPath();
        panel.fireChangeEvent();
    }//GEN-LAST:event_examplesTree_clicked
    //=========================================================================
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JComboBox componentSelection;
    private javax.swing.JTree examplesTree;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabelMessage;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane2;
    // End of variables declaration//GEN-END:variables

    /**
     * @return the examplesTree
     */
    public javax.swing.JTree getExamplesTree() {
        return examplesTree;
    }

    /**
     * @return the componentSelection
     */
    public javax.swing.JComboBox getComponentSelection() {
        return componentSelection;
    }
}
